import {Dictionary} from "./types/Types";
import {addExtendAgentToUrl, buildFullUrl, clientEnv, safeToString} from "./function/CommonUtils";
import {AbstractWebOffice} from "./AbstractWebOffice";

export class NtkoWebOffice extends AbstractWebOffice {
    _ready: boolean = false;
    private static _pluginType: string = 'ntko';

    constructor(wrapperId: string, options: Dictionary) {
        super(wrapperId, options);
        const self = this;
        const browserInfo = clientEnv();
        setTimeout(()=>{
            if (!self.pluginObj().ToolBars)
                self._ready = true;
        },200);
        self.pluginObj().ToolBars = self.options.officeToolbars;
        self.pluginObj().CustomToolBar = self.options.customToolbar;
        self.pluginObj().Menubar = self.options.menubar;
        self.pluginObj().Titlebar = self.options.titlebar

        if (browserInfo.browser == 'ie') {
            let eventListener = 'function(weboffice,pluginObj){ \n ' +
                'function pluginObj::OnDocumentOpened() { \n ' +
                '    weboffice._onDocumentOpened.apply(weboffice,arguments);\n ' +
                '}   \n }';
            eval('(0,' + eventListener + ')')(self, self.pluginObj());

        } else {
            self.pluginObj().addEventListener('OnDocumentOpened', function () {
                self._onDocumentOpened.apply(self, arguments);
            });
        }
        setTimeout(function () {
            if (self.options.fileDownloadUrl) {
                if ("createNew" == self.options.fileDownloadUrl)
                    self.createFile();
                else
                    self.openRemoteFile(self.options.fileDownloadUrl, false);
            } else {
                self._ready = true;
            }
        }, 10);

    }

    _onDocumentOpened(file: string, doc: any) {
        const self = this;
        self._officeApp = doc.Application;
        setTimeout(function () {
            self._initDocument().then(function (result) {
                if (result.errorCode == '0')
                    self._ready = true;
            }, function (error) {
                console.error(error.errorMessage);
                throw new Error(error.errorMessage);
            });
        }, 10)

    }

    protected _createObjectHtml(objectId: string) {
        let finalClassId = "A64E3073-2016-4baf-A89D-FFE1FAA10EC0",
            finalCodeBase = buildFullUrl(this.options.serverPage + "/OfficeControl.cab#version=6,0,1,0"),
            objectElArr = [];
        const browserInfo = clientEnv();
        if (browserInfo.browser == "ie") {
            if (window.navigator.platform == "Win64") {
                finalClassId = "A64E3073-2016-4baf-A89D-FFE1FAA10EE0";
                finalCodeBase = buildFullUrl(this.options.serverPage + "/OfficeControlx64.cab#version=6,0,1,0");
            }

            objectElArr.push('<!-- 用来产生编辑状态的ActiveX控件的JS脚本-->   ');
            objectElArr.push('<!-- 因为微软的ActiveX新机制，需要一个外部引入的js-->   ');
            objectElArr.push('<object id="' + objectId + '" classid="clsid:' + finalClassId + '"');
            objectElArr.push('codebase="' + finalCodeBase + '" width="100%" height="100%">   ');
            objectElArr.push('<param name="IsUseUTF8URL" value="1">   ');
            objectElArr.push('<param name="IsUseUTF8Data" value="1">   ');
            objectElArr.push('<param name="ProductCaption" value="' + this.options.productCaption + '">');
            objectElArr.push('<param name="ProductKey" value="' + this.options.productKey + '">');
            objectElArr.push('<SPAN STYLE="color:red">不能装载文档控件。请在检查浏览器的选项中检查浏览器的安全设置。</SPAN>   ');
            objectElArr.push('</object>');
        } else if (browserInfo.browser == "firefox" || browserInfo.browser == 'chrome') {
            objectElArr.push('<object id="' + objectId + '" type="application/ntko-plug"  codebase="' + finalCodeBase + '" width="100%" height="100%" ForOnSaveToURL="_savetourlcallback" ');
            /*objectElArr.push('ForOnDocumentOpened="_onDocumentOpened"');
            objectElArr.push('ForOnWordWPSSelChange="_onWordWpsSelChange"');
            objectElArr.push('ForOnSaveAsOtherFormatToUrl="saveasotherurl"');
            objectElArr.push('ForOnDoWebGet="dowebget"');
            objectElArr.push('ForOnDoWebExecute="webExecute"');
            objectElArr.push('ForOnDoWebExecute2="webExecute2"');
            objectElArr.push('ForOnFileCommand="FileCommand"');*/
            objectElArr.push('_IsUseUTF8URL="1"   ');
            objectElArr.push('_ProductCaption="' + this.options.productCaption + '"');
            objectElArr.push('_ProductKey="' + this.options.productKey + '"');
            objectElArr.push('_IsUseUTF8Data="1"   ');
            objectElArr.push('clsid="{' + finalClassId + '}" >');
            objectElArr.push('<SPAN STYLE="color:red">尚未安装NTKO Web FireFox跨浏览器插件。请点击<a href="' + buildFullUrl(this.options.serverPage + "/ntko.exe") + '">安装组件</a></SPAN>   ');
            objectElArr.push('</object>   ');
        }

        return objectElArr.join("");
    }


    private _buttonControlByTypeAndId(type: number, id: number, enabled: boolean) {
        const controls = this.activeDocument().CommandBars.FindControls(type, id);
        if (controls.Count > 0) {
            for (let i = 1; i <= controls.Count; i++) {
                const control = controls.Item(i);
                control.Enabled = enabled;
            }
        }
    }

    private _getCommandBar(barName: string) {
        return this.activeDocument().CommandBars.Item(barName);
    }

    private _getControlByName(barName: string, controlName: string) {
        const commandBar = this._getCommandBar(barName);
        if (commandBar == null || commandBar == undefined)
            return null;
        return commandBar.Controls.Item(controlName);
    }

    private _initFileOpenDialog() {
        const self = this;
        const fileDialog = self.officeApp().Application.FileDialog(1);
        const firstFilter = fileDialog.Filters.Item(1);
        if (firstFilter.Description.indexOf("常用文件") == -1) {
            fileDialog.Filters.Add("常用文件", "*.wps;*.wpt;*.doc;*.dot;*.rtf;*.docx;*.pdf", 2);
            fileDialog.Filters.Delete(1);
            fileDialog.Filters.Add(firstFilter.Description, firstFilter.Extensions, 2);
        }
        return fileDialog;
    }

    private _disableSameButton(readOnly: boolean) {
        const self = this;
        //禁用"新建"菜单
        self.pluginObj().FileNew = false;
        //禁用打印预览
        self.pluginObj().FilePrintPreview = false;
        if (readOnly) {
            //禁用"打开"菜单
            self.pluginObj().FileOpen = false;
            //禁用分页符
            self.pluginObj().ShowCommandBar(92101, false);
        } else {
            //启用"打开"菜单
            self.pluginObj().FileOpen = true;
            //启用分页符
            self.pluginObj().ShowCommandBar(92101, true);
        }
    }

    private _initDocument(): Promise<any> {
        const self = this;
        return new Promise(function (resolve, reject) {
            try {
                const openMode = self.options.openMode;
                if (self.options.userName)
                    self.officeApp().UserName = self.options.userName;
                self._disableSameButton(openMode != "docNormalEdit");
                try {
                    self._publicDocumentInitialize();
                } catch (e) {
                    reject({errorCode: '-1', errorMessage: e});
                }
                if (self.options.jsFunction_OnWordDataRegionClick && (self.options.openMode == "docNormalEdit" || self.options.openMode == "docSubmitForm" || self.options.openMode == "docAdmin")) {

                    const browserInfo = clientEnv();
                    if (browserInfo.browser == 'ie') {
                        let eventListener = 'function(weboffice,pluginObj){ \n ' +
                            'function pluginObj::OnWordWPSSelChange() { \n ' +
                            '   weboffice._onWordWpsSelChange.apply(weboffice,arguments);\n ' +
                            '}   ' +
                            '\n }';
                        eval('(0,' + eventListener + ')')(self, self.pluginObj());
                    } else {
                        self.pluginObj().addEventListener('OnWordWPSSelChange', function () {
                            self._onWordWpsSelChange.apply(self, arguments);
                        });
                    }
                }
                resolve({errorCode: '0', errorMessage: 'OK'});
            } catch (e) {
                reject({errorCode: '-1', errorMessage: e});
            }
            // },defer.reject);

        });

    }

    private fullScreen() {
        this.officeApp().FullScreen();
    }

    public isDirty() {
        return !this.activeDocument().Saved;
    }

    public saveAs(fileName?: string) {
        this.pluginObj().ShowDialog(3);
    }


    public deleteBookmark(name: string): void {
        super.deleteBookmark(name);
        const that = this;
        delete that._bookmarkRange[safeToString(name).toLowerCase()];
    }


    public enableToolbars(enable: boolean = true) {
        this.options.officeToolbars = enable;
        this.pluginObj().ToolBars = enable;
    }

    public print(): void {
        const that = this;
        const control = that._getControlByName("File", "打印(&P)...");
        if (control) {
            control.Execute();
        } else {
            that.pluginObj().ShowDialog(4);
        }
    }

    public importFile(): Promise<any> {
        const that = this;
        return new Promise<any>(function (resolve, reject) {
            try {
                that.pluginObj().ShowDialog(1);
            } catch (e) {
                reject({errorCode: '-1', errorMessage: e, result: false});
            }
        })

    }

    public printPreview() {
        this.pluginObj().PrintPreview()
    }

    public closePrintPreview() {
        this.pluginObj().ExitPrintPreview();
    }


    public openRemoteFile(fileUrl: string, readOnly: boolean): Promise<any> {
        const that = this;
        return new Promise<any>(function (resolve, reject) {
            try {
                that._ready = false;
                that._officeApp = null;
                try {
                    that.pluginObj().OpenFromURL(buildFullUrl(fileUrl), readOnly, "WPS.Document");
                } catch (e) {
                    try {
                        that.pluginObj().OpenFromURL(buildFullUrl(fileUrl), readOnly, "KWPS.Document");
                    } catch (e) {
                        that.pluginObj().OpenFromURL(buildFullUrl(fileUrl), readOnly, "Word.Document");
                    }
                }
                let tryCount = 0;
                const intervalControl = setInterval(function () {
                    if (that._ready) {
                        clearInterval(intervalControl);
                        resolve({errorCode: '0', errorMessage: '', result: that});
                    }
                    //尝试10分钟如果还没有初始化完成，则认为失败
                    if (tryCount > 600) {
                        clearInterval(intervalControl);
                        reject({errorCode: '-1', errorMessage: '控件初始化失败，请联系管理员！'});
                    }
                    tryCount++;
                }, 1000);
            } catch (e) {
                reject({errorCode: '-1', errorMessage: e, result: false});
            }

        })

    }


    public saveToUrl(tempUrl?: string): Promise<any> {
        const self = this;
        const url = tempUrl || self.options.saveFilePage;
        return new Promise(function (resolve, reject) {
            let unprotect = false;
            try {
                const browserInfo = clientEnv();
                if (self._protectionType > -1) {
                    unprotect = true;
                    self.activeDocument().Unprotect(self._protectPass);
                }
                if (self._protectionType == 3) {
                    self._deleteAllEditors();
                }
                if (browserInfo.browser != 'ie') {
                    window['_savetourlcallback'] = function (type: number, code: number, html: string) {
                        if (self._protectionType == 3) {
                            self._recoveryAllEditors();
                        }
                        if (unprotect && self._protectionType > -1)
                            self.activeDocument().Protect(self._protectionType, true, self._protectPass);
                        if (code == 0)
                            resolve({errorCode: "0", result: html, errorMessage: "OK"});
                        else
                            reject({errorCode: "-1", result: false, errorMessage: html});
                    }
                }
                let r = self.pluginObj().SaveToURL(addExtendAgentToUrl(url, NtkoWebOffice._pluginType), "ntkoFile", "", "", 0);
                if (browserInfo.browser == 'ie') {
                    if (self._protectionType == 3) {
                        self._recoveryAllEditors();
                    }
                    if (unprotect && self._protectionType > -1)
                        self.activeDocument().Protect(self._protectionType, true, self._protectPass);
                    resolve({errorCode: "0", result: r, errorMessage: "OK"});
                }
            } catch (e) {
                if (unprotect && self._protectionType > -1)
                    self.activeDocument().Protect(self._protectionType, true, self._protectPass);
                reject({errorCode: "-1", result: false, errorMessage: "fail!"});
            }
        });
    }

    public getAllBookmarkValue(): Object {
        const that = this;
        const fieldData: Dictionary = {};
        for (let bookmarkName in that._bookmarkRange) {
            const originName=this._lowerCaseNameToOriginMap[bookmarkName]||bookmarkName;
            const value = that.getBookmarkValue(originName);
            fieldData[originName] = value;
        }
        return fieldData;
    }


    public createFile(): Promise<any> {
        const that = this;
        return new Promise(function (resolve, reject) {
            try {
                const browserInfo = clientEnv();
                that._ready = false;
                try {
                    that.pluginObj().CreateNew("WPS.Document");
                } catch (e) {
                    try {
                        that.pluginObj().CreateNew("KWPS.Document");
                    } catch (e) {
                        that.pluginObj().CreateNew("Word.Document");
                    }
                }

                let tryCount = 0;
                const intervalControl = setInterval(function () {
                    if (that._ready) {
                        clearInterval(intervalControl);
                        resolve({errorCode: '0', errorMessage: '', result: that});
                    }
                    //尝试半分钟如果还没有初始化完成，则认为失败
                    if (tryCount > 30) {
                        clearInterval(intervalControl);
                        reject({errorCode: '-1', errorMessage: '控件初始化失败，请联系管理员！'});
                    }
                    tryCount++;
                }, 1000);
            } catch (e) {
                reject({errorCode: '-1', errorMessage: e, result: false});
            }
        })
    }


    public openLocalFile(filePath: string, readOnly: boolean = false): Promise<any> {
        const that = this;
        return new Promise(function (resolve, reject) {
            try {
                const browserInfo = clientEnv();
                that._ready = false;
                try {
                    that.pluginObj().OpenLocalFile(filePath, readOnly, "WPS.Document");
                } catch (e) {
                    try {
                        that.pluginObj().OpenLocalFile(filePath, readOnly, "KWPS.Document");
                    } catch (e) {
                        that.pluginObj().OpenLocalFile(filePath, readOnly, "Word.Document");
                    }
                }
                let tryCount = 0;
                const intervalControl = setInterval(function () {
                    if (that._ready) {
                        clearInterval(intervalControl);
                        resolve({errorCode: '0', errorMessage: '', result: that});
                    }
                    //尝试半分钟如果还没有初始化完成，则认为失败
                    if (tryCount > 30) {
                        clearInterval(intervalControl);
                        reject({errorCode: '-1', errorMessage: '控件初始化失败，请联系管理员！'});
                    }
                    tryCount++;
                }, 1000);
            } catch (e) {
                reject({errorCode: '-1', errorMessage: e, result: false});
            }
        })
    }

    public insertDocumentFromUrl(documentUrl: string): Promise<boolean> {
        const that = this;
        const browserInfo = clientEnv();
        return new Promise(function (resolve, reject) {
            if (browserInfo.browser != 'ie') {
                that.pluginObj().addEventListener('OnAddTemplateFromURL', function (type: any, code: any, html: any) {
                    if (html == 'ok')
                        resolve(true);
                    else
                        reject(false);
                });
            }
            that.pluginObj().AddTemplateFromURL(buildFullUrl(documentUrl));
            if (browserInfo.browser == 'ie')
                resolve(true);
        });
    }


}